home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / gxu / shownormal.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-30  |  14.3 KB  |  475 lines

  1. /*//////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: stripoutline.cpp
  4. //
  5. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. //
  8. //////////////////////////////////////////////////////////////////////////////*/
  9.  
  10. #include "pchgxu.h"
  11.  
  12. #include "ShowNormal.h"
  13.  
  14. #define SKINNEDFVF D3DFVF_XYZB4|D3DFVF_NORMAL
  15. #define SKINNEDFVFSTRIDE 40
  16.  
  17. #define INDEXSKINNEDFVF D3DFVF_XYZB5|D3DFVF_NORMAL|D3DFVF_LASTBETA_D3DCOLOR
  18. #define INDEXSKINNEDFVFSTRIDE 44
  19.  
  20. CShowNormals::CShowNormals()
  21.   :m_pDevice(NULL),
  22.     m_pVertexBuffer(NULL),
  23.     m_bSkinning(FALSE),
  24.     m_bIndexedSkinning(FALSE),
  25.     m_bHWVertexShaders(FALSE),
  26.     m_rgaeAttributeTable(NULL),
  27.     m_caeAttributeTable(0)
  28. {
  29. }
  30.  
  31. CShowNormals::~CShowNormals()
  32. {
  33.     GXRELEASE(m_pVertexBuffer);
  34.     GXRELEASE(m_pDevice);
  35.  
  36.     delete []m_rgaeAttributeTable;
  37. }
  38.  
  39.     // dwTexStage is the texture stage to use for drawing vectors, 
  40.     //                  if 0xffffffff then the normal field will be used
  41. HRESULT
  42. CShowNormals::Init
  43.     (
  44.     ID3DXBaseMesh *ptmMesh, 
  45.     DWORD dwTexStage,
  46.     float fLength
  47.     )
  48. {
  49.     HRESULT hr = S_OK;
  50.     PBYTE pbSrc = NULL;
  51.     PBYTE pbDest = NULL;
  52.     DWORD iVertex;
  53.     DWORD cVertices;
  54.     DXCrackFVF cfvfDest(D3DFVF_XYZ);
  55.     CD3DXCrackDecl1 cdSrc;
  56.     D3DXVECTOR3 vPos;
  57.     D3DXVECTOR3 vNormal;
  58.     D3DXVECTOR3 vZero(0.0f, 0.0f, 0.0f);
  59.     float fSum;
  60.     float fWeight;
  61.     DWORD iWeight;
  62.     D3DCAPS9 Caps;
  63.     DWORD cbSizeOfVector;
  64.     DWORD cWeights;
  65.     D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE];
  66.     UINT iAttrib;
  67.  
  68.     m_fScale = fLength;
  69.  
  70.     hr = CreateEmptyOutline();
  71.     if (FAILED(hr))
  72.         goto e_Exit;
  73.  
  74.     if (ptmMesh == NULL)
  75.         goto e_Exit;
  76.  
  77.     cVertices = ptmMesh->GetNumVertices();
  78.  
  79.     ptmMesh->GetDeclaration(pDecl);
  80.     cdSrc.SetDeclaration(pDecl);;
  81.  
  82.     // if the texture stage is 
  83.     if ((dwTexStage != UNUSED32) && !cdSrc.BTexCoord(dwTexStage))
  84.         goto e_Exit;
  85.  
  86.     if (dwTexStage != UNUSED32)
  87.         cbSizeOfVector = x_rgcbTypeSizes[cdSrc.rgpTextureElements[dwTexStage]->Type];
  88.  
  89.     if ((dwTexStage == UNUSED32) && !cdSrc.BNormal())
  90.         goto e_Exit;
  91.  
  92.     ptmMesh->GetDevice(&m_pDevice);
  93.  
  94.     m_pDevice->GetDeviceCaps(&Caps);
  95.     m_bHWVertexShaders = Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
  96.  
  97.     hr = ptmMesh->GetAttributeTable(NULL, &m_caeAttributeTable);
  98.     if (FAILED(hr))
  99.         goto e_Exit;
  100.  
  101.     if (m_caeAttributeTable == 0)
  102.     {
  103.         // not attribute sorted!  just return for now
  104.         goto e_Exit;
  105.     }
  106.  
  107.     m_rgaeAttributeTable = new D3DXATTRIBUTERANGE[m_caeAttributeTable];
  108.     if (m_rgaeAttributeTable == NULL)
  109.     {
  110.         hr = E_OUTOFMEMORY;
  111.         goto e_Exit;
  112.     }
  113.  
  114.     if ((cdSrc.CWeights() > 0) && !cdSrc.BIndexedWeights())
  115.     {
  116.         m_bSkinning = TRUE;
  117.         m_bIndexedSkinning = FALSE;
  118.         cfvfDest = DXCrackFVF(SKINNEDFVF);
  119.     }
  120.     else if (cdSrc.CWeights() > 0)
  121.     {
  122.         m_bSkinning = TRUE;
  123.         m_bIndexedSkinning = TRUE;
  124.         cfvfDest = DXCrackFVF(INDEXSKINNEDFVF);
  125.     }
  126.     else
  127.     {
  128.         m_bSkinning = FALSE;
  129.     }
  130.  
  131.     hr = ptmMesh->GetAttributeTable(m_rgaeAttributeTable, NULL);
  132.     if (FAILED(hr))
  133.         goto e_Exit;
  134.  
  135.     cVertices = 0;
  136.     for (iAttrib = 0; iAttrib < m_caeAttributeTable; iAttrib++)
  137.     {
  138.         cVertices = max(cVertices, m_rgaeAttributeTable[iAttrib].VertexStart + m_rgaeAttributeTable[iAttrib].VertexCount);
  139.     }
  140.     // get the maximum vertex index
  141.  
  142.     hr = m_pDevice->CreateVertexBuffer(cVertices * 2 * cfvfDest.m_cBytesPerVertex, 
  143.                     D3DUSAGE_WRITEONLY|(m_bHWVertexShaders ? 0:D3DUSAGE_SOFTWAREPROCESSING), 
  144.                     cfvfDest.m_dwFVF, D3DPOOL_MANAGED, &m_pVertexBuffer, NULL);
  145.  
  146.     hr = ptmMesh->LockVertexBuffer(D3DLOCK_READONLY, (PVOID*)&pbSrc);
  147.     if (FAILED(hr))
  148.     {
  149.         hr = CreateEmptyOutline();
  150.         goto e_Exit;   
  151.     }
  152.  
  153.     hr = m_pVertexBuffer->Lock(0, 0, (PVOID*)&pbDest, D3DLOCK_NOSYSLOCK);
  154.     if (FAILED(hr))
  155.         goto e_Exit;   
  156.  
  157.     if (m_bSkinning)
  158.     {
  159.         // first figure out the counts for the number of creases per attribute group
  160.         for (iVertex = 0; iVertex < cVertices; iVertex++)
  161.         {
  162.             vPos = *cdSrc.PvGetPosition(pbSrc);
  163.  
  164.             // if use the normal, easy
  165.             if (dwTexStage == UNUSED32)
  166.             {
  167.                 vNormal = *cdSrc.PvGetNormal(pbSrc);
  168.             }
  169.             else  // else grab a texture coordinate as a vector
  170.             {
  171.                 // set all parts of the vector to zero
  172.                 memset(&vNormal, 0, sizeof(D3DXVECTOR3));
  173.  
  174.                 // copy the parts found in the mesh
  175.                 memcpy(&vNormal, pbSrc + cdSrc.rgpTextureElements[dwTexStage]->Offset, cbSizeOfVector);
  176.  
  177.             }
  178.             D3DXVec3Normalize(&vNormal, &vNormal);
  179.  
  180.  
  181.             // first copy the weights that exist in the source
  182.             fSum = 0.0f;
  183.             cWeights = cdSrc.BIndexedWeights() ? cdSrc.CWeights() - 1: cdSrc.CWeights();
  184.             for (iWeight = 0; iWeight < cWeights; iWeight++)
  185.             {
  186.                 fWeight = cdSrc.FGetWeight(pbSrc, iWeight);
  187.                 fSum += fWeight;
  188.  
  189.                 cfvfDest.SetWeight(pbDest, iWeight, fWeight);
  190.                 cfvfDest.SetWeight(pbDest + cfvfDest.m_cBytesPerVertex, iWeight, fWeight);
  191.             }
  192.  
  193.             // now set the implied weight - always exists in dest
  194.             cfvfDest.SetWeight(pbDest, iWeight, 1.0f - fSum);
  195.             cfvfDest.SetWeight(pbDest + cfvfDest.m_cBytesPerVertex, iWeight, 1.0f - fSum);
  196.             iWeight += 1;
  197.  
  198.             // set any other weights that are unused to 0.0f
  199.             cWeights = cdSrc.BIndexedWeights() ? cfvfDest.CWeights() - 1: cfvfDest.CWeights();
  200.             for (; iWeight < cWeights; iWeight++)
  201.             {
  202.                 cfvfDest.SetWeight(pbDest, iWeight, 0.0f);
  203.                 cfvfDest.SetWeight(pbDest + cfvfDest.m_cBytesPerVertex, iWeight, 0.0f);
  204.             }
  205.  
  206.             // if indexed skinning, copy the indices
  207.             if (cdSrc.BIndexedWeights())
  208.             {
  209.                 cfvfDest.SetIndices(pbDest, *cdSrc.PdwGetIndices(pbSrc));
  210.                 cfvfDest.SetIndices(pbDest + cfvfDest.m_cBytesPerVertex, *cdSrc.PdwGetIndices(pbSrc));
  211.             }
  212.  
  213.             // set one normal to zero and the other to the correct value
  214.             //   both points have the same position though.  the normal
  215.             //   is added post skinning 
  216.  
  217.             // normal to zero
  218.             cfvfDest.SetPosition(pbDest, &vPos);
  219.             cfvfDest.SetNormal(pbDest, &vZero);
  220.             pbDest += cfvfDest.m_cBytesPerVertex;
  221.  
  222.             // correct normal
  223.             cfvfDest.SetPosition(pbDest, &vPos);
  224.             cfvfDest.SetNormal(pbDest, &vNormal);
  225.             pbDest += cfvfDest.m_cBytesPerVertex;
  226.  
  227.             pbSrc += cdSrc.m_cBytesPerVertex;
  228.         }
  229.     }
  230.     else
  231.     {
  232.         // first figure out the counts for the number of creases per attribute group
  233.         for (iVertex = 0; iVertex < cVertices; iVertex++)
  234.         {
  235.             vPos = *cdSrc.PvGetPosition(pbSrc);
  236.             // show binormals
  237.  
  238.             // if use the normal, easy
  239.             if (dwTexStage == UNUSED32)
  240.             {
  241.                 vNormal = *cdSrc.PvGetNormal(pbSrc);
  242.             }
  243.             else  // else grab a texture coordinate as a vector
  244.             {
  245.                 // set all parts of the vector to zero
  246.                 memset(&vNormal, 0, sizeof(D3DXVECTOR3));
  247.  
  248.                 // copy the parts found in the mesh
  249.                 memcpy(&vNormal, pbSrc + cdSrc.rgpTextureElements[dwTexStage]->Offset, cbSizeOfVector);
  250.  
  251.             }
  252.             D3DXVec3Normalize(&vNormal, &vNormal);
  253.             vNormal *= fLength;
  254.             pbSrc += cdSrc.m_cBytesPerVertex;
  255.  
  256.             cfvfDest.SetPosition(pbDest, &vPos);
  257.             pbDest += cfvfDest.m_cBytesPerVertex;
  258.  
  259.             vPos += vNormal;
  260.             cfvfDest.SetPosition(pbDest, &vPos);
  261.             pbDest += cfvfDest.m_cBytesPerVertex;
  262.         }
  263.     }
  264.  
  265. e_Exit:
  266.  
  267.     if (pbSrc != NULL)
  268.         ptmMesh->UnlockVertexBuffer();
  269.  
  270.     if (pbDest != NULL)
  271.         m_pVertexBuffer->Unlock();
  272.  
  273.     return hr;
  274. }
  275.  
  276. // matrix names for variables in FX file
  277. const char *x_rgszMatrix[] =
  278. {
  279.  "mWd1", "mWd2", "mWd3", "mWd4", "mWd5", "mWd6", "mWd7", "mWd8", "mWd9",
  280.  "mWd10", "mWd11", "mWd12", "mWd13", "mWd14", "mWd15", "mWd16", "mWd17", "mWd18", "mWd19",
  281.  "mWd20", "mWd21", "mWd22", "mWd23", "mWd24", "mWd25", "mWd26", "mWd27", "mWd28"
  282. };
  283.  
  284. HRESULT
  285. CShowNormals::Draw
  286.     (
  287.     DWORD iAttrib, 
  288.     DWORD iVertex,
  289.     LPD3DXEFFECT pfxShowNormals, 
  290.     LPD3DXEFFECT pfxColor, 
  291.     DWORD dwColor,
  292.     D3DXMATRIX *rgmIndexedMatrices,
  293.     DWORD cIndexedMatrices
  294.     )
  295. {
  296.     HRESULT hr;
  297.     LPD3DXEFFECT pfxCurrent;
  298.     DWORD dwFVF;
  299.     UINT iPass;
  300.     UINT cPasses;
  301.     DWORD cBytesPerVertex;
  302.     D3DXMATRIX matWorld;
  303.     D3DXMATRIX matView;
  304.     D3DXMATRIX matProj;
  305.     D3DXMATRIX matTot;
  306.     D3DXVECTOR4 vScale(m_fScale, 0.0f, 0.0f,0.0f);
  307.     D3DXCOLOR vClr(dwColor);
  308.     BOOL dwSoftwareMode;
  309.     DWORD cLines;
  310.     DWORD cLinesCur;
  311.     DWORD iVertexStart;
  312.     DWORD iMatrix;
  313.     BOOL bChangedSWMode = FALSE;
  314.     DWORD iSubset;
  315.  
  316.     if (m_bSkinning)
  317.     {
  318.         if (!m_bIndexedSkinning)
  319.         {
  320.             pfxCurrent = pfxShowNormals;
  321.             dwFVF = SKINNEDFVF;
  322.             cBytesPerVertex = SKINNEDFVFSTRIDE;
  323.             pfxShowNormals->SetTechnique(pfxShowNormals->GetTechnique(0));
  324.  
  325.             m_pDevice->GetTransform(D3DTS_VIEW,&matView);
  326.             m_pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
  327.             m_pDevice->GetTransform(D3DTS_WORLD,&matWorld);
  328.  
  329.             //D3DXMatrixMultiply(&matTot, &matWorld,&matView);
  330.             D3DXMatrixMultiply(&matTot,&matView,&matProj);
  331.             pfxShowNormals->SetMatrix("mTot", &matTot);                       
  332.  
  333.             m_pDevice->GetTransform(D3DTS_WORLD,&matWorld);
  334.             pfxShowNormals->SetMatrix("mWd1", &matWorld);                       
  335.  
  336.             m_pDevice->GetTransform(D3DTS_WORLD1,&matWorld);
  337.             pfxShowNormals->SetMatrix("mWd2", &matWorld);                       
  338.  
  339.             m_pDevice->GetTransform(D3DTS_WORLD2,&matWorld);
  340.             pfxShowNormals->SetMatrix("mWd3", &matWorld);                       
  341.  
  342.             m_pDevice->GetTransform(D3DTS_WORLD3,&matWorld);
  343.             pfxShowNormals->SetMatrix("mWd4", &matWorld);                       
  344.  
  345.         }
  346.         else
  347.         {
  348.             dwFVF = INDEXSKINNEDFVF;
  349.             pfxCurrent = pfxShowNormals;
  350.             cBytesPerVertex = INDEXSKINNEDFVFSTRIDE;
  351.             pfxShowNormals->SetTechnique(pfxShowNormals->GetTechnique(1));
  352.  
  353.             m_pDevice->GetTransform(D3DTS_VIEW,&matView);
  354.             m_pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
  355.  
  356.             D3DXMatrixMultiply(&matTot,&matView,&matProj);
  357.             pfxShowNormals->SetMatrix("mTot", &matTot);                       
  358.  
  359.             pfxShowNormals->SetMatrixArray("mWorlds", rgmIndexedMatrices, 28);
  360.  
  361.             //for (iMatrix = 0; iMatrix < cIndexedMatrices; iMatrix++)
  362.             //{
  363.               //  pfxShowNormals->SetMatrix(x_rgszMatrix[iMatrix], &rgmIndexedMatrices[iMatrix]);
  364.             //}
  365.         }
  366.  
  367.         pfxShowNormals->SetVector("vScl", &vScale);                       
  368.         pfxShowNormals->SetVector("vClr", (D3DXVECTOR4*)&vClr);                       
  369.  
  370.         dwSoftwareMode = m_pDevice->GetSoftwareVertexProcessing();
  371.         if (!m_bHWVertexShaders)
  372.         {
  373.             bChangedSWMode = TRUE;
  374.             m_pDevice->SetSoftwareVertexProcessing(TRUE);
  375.         }
  376.         // if in the wrong mode, then switch
  377.         else if (dwSoftwareMode && m_bHWVertexShaders)
  378.         {
  379.             bChangedSWMode = TRUE;
  380.             m_pDevice->SetSoftwareVertexProcessing(FALSE);
  381.         }
  382.     }
  383.     else
  384.     {
  385.         pfxCurrent = pfxColor;
  386.         dwFVF = D3DFVF_XYZ;
  387.         cBytesPerVertex = 12;
  388.  
  389.         pfxCurrent->SetVector("vClr", (D3DXVECTOR4*)&vClr);                       
  390.     }
  391.  
  392.     if ((iAttrib < m_caeAttributeTable) && (m_rgaeAttributeTable[iAttrib].AttribId == iAttrib))
  393.     {
  394.         iSubset = iAttrib;
  395.     }
  396.     else
  397.     {
  398.         // look for the correct attribute table entry to draw
  399.         for (iSubset = 0; iSubset < m_caeAttributeTable; iSubset++)
  400.         {
  401.             if (m_rgaeAttributeTable[iSubset].AttribId == iAttrib)
  402.             {
  403.                 break;
  404.             }
  405.         }
  406.     }
  407.  
  408.     if (iSubset < m_caeAttributeTable)
  409.     {
  410.         if (m_rgaeAttributeTable[iSubset].VertexCount > 0)
  411.         {
  412.             pfxCurrent->Begin(&cPasses, 0);
  413.  
  414.             for (iPass = 0; iPass < cPasses; iPass++)
  415.             {
  416.                 m_pDevice->SetFVF(dwFVF);
  417.  
  418.                 pfxCurrent->BeginPass(iPass);
  419.  
  420.                 m_pDevice->SetStreamSource(0, m_pVertexBuffer, 0, cBytesPerVertex);
  421.  
  422.                 if (iVertex == UNUSED32)
  423.                 {
  424.                     iVertexStart = m_rgaeAttributeTable[iSubset].VertexStart;
  425.                     cLines = m_rgaeAttributeTable[iSubset].VertexCount;
  426.  
  427.                     while (cLines > 0)
  428.                     {
  429.                         cLinesCur = min(cLines, (0xffff / 2));
  430.  
  431.                         hr = m_pDevice->DrawPrimitive(D3DPT_LINELIST, 
  432.                                                      iVertexStart * 2, 
  433.                                                      cLinesCur);
  434.                         if (FAILED(hr))
  435.                             return hr;
  436.  
  437.                         iVertexStart += cLinesCur * 2;
  438.                         cLines -= cLinesCur;
  439.                     }
  440.                 }
  441.                 else
  442.                 {
  443.                     hr = m_pDevice->DrawPrimitive(D3DPT_LINELIST, 
  444.                                                  iVertex * 2, 1);
  445.                 }
  446.  
  447.                 pfxCurrent->EndPass();
  448.             }
  449.  
  450.             pfxCurrent->End();
  451.  
  452.         }
  453.     }
  454.  
  455.     if (bChangedSWMode)
  456.     {
  457.         m_pDevice->SetSoftwareVertexProcessing(dwSoftwareMode);
  458.     }
  459.  
  460.     return S_OK;
  461. }
  462.  
  463. HRESULT
  464. CShowNormals::CreateEmptyOutline()
  465. {
  466.     delete []m_rgaeAttributeTable;
  467.     m_rgaeAttributeTable = NULL;
  468.     m_caeAttributeTable = 0;
  469.  
  470.     GXRELEASE(m_pVertexBuffer);
  471.     GXRELEASE(m_pDevice);
  472.  
  473.     return S_OK;
  474. }
  475.